home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / ulib / fixdir.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  4KB  |  184 lines

  1. /***********************************************************************
  2.  * $Id: fixdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
  3.  *
  4.  *.  Copyright(c) 1993,1994 by T.C. Zhao
  5.  *   All rights reserved.
  6.  *.
  7.  *
  8.  * Given a directory name, expand it to absolute path.
  9.  * Or do the reverse.
  10.  *
  11.  ***********************************************************************/
  12. #if !defined(lint) && defined(F_ID)
  13. char *id_fixdir = "$Id: fixdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
  14. #endif
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "unistd.h"
  19. #include <pwd.h>
  20. #include "ulib.h"
  21.  
  22. /************************************************************
  23.  * fix the tail of an expanded directory
  24.  ***********************************************************/
  25. char *
  26. fix_dir_tail(char dir[])
  27. {
  28.     return (dir[strlen(dir) - 1] != '/') ? strcat(dir, "/") : dir;
  29. }
  30.  
  31. /*
  32.  * add one component to a dirname
  33.  */
  34. static void
  35. add_one(char dir[], char one[])
  36. {
  37.  
  38.     char *q;
  39.  
  40.     if (one[0] == '.' && one[1] == '.' && one[2] == '\0')
  41.       {
  42.       if ((q = strrchr(dir, '/')) && q != dir)
  43.           *q = '\0';
  44.       }
  45.     else if (one[0] == '~')
  46.       {
  47.       if (one[1] == '\0')
  48.         {            /* must be ~/ ... */
  49.         strcat(dir, (q = getenv("HOME")) ? q : "/");
  50.         }
  51.       else
  52.         {            /* must be ~name */
  53.         struct passwd *p = getpwnam(one + 1);
  54.         strcat(dir, p ? p->pw_dir : "/");
  55.         endpwent();
  56.         }
  57.       }
  58.     else if (!(one[0] == '.' && one[1] == '\0'))
  59.       {
  60.       strcat(strcat(dir, "/"), one);
  61.       }
  62. }
  63.  
  64. /**************************************************************
  65.  * complete a dirname. If dir is NULL, return the local copy.
  66.  * ugly, but works for ./../../foo/./../ etc.
  67.  **************************************************************/
  68.  
  69. char *
  70. fix_dirname(char dir[])
  71. {
  72.     static char ldir[PATH_MAX], one[PATH_MAX];
  73.     char *p = ldir, *q = one;
  74.  
  75.  
  76.     if (!dir || !*dir)
  77.     return getcwd(dir ? dir : ldir, PATH_MAX - 2);
  78.  
  79.     strcpy(ldir, dir);
  80.  
  81.     if (ldir[0] != '/' && ldir[0] != '~')
  82.     getcwd(dir, PATH_MAX - 2);
  83.     else
  84.     dir[0] = '\0';
  85.  
  86.     while (*p)
  87.       {
  88.       if (*p == '/')
  89.         {
  90.         *q = '\0';
  91.         if (q > one)
  92.             add_one(dir, (q = one));
  93.         }
  94.       else
  95.           *q++ = *p;
  96.       p++;
  97.       }
  98.  
  99.     *q = '\0';
  100.     if (q > one)
  101.     add_one(dir, one);
  102.     return dir;
  103. }
  104.  
  105. /*****************************************************************
  106.  * Search  str for pat, and if found, replace it with rep
  107.  ****************************************************************/
  108. static void
  109. pat_replace(char str[], const char *pat, const char *rep)
  110. {
  111.     char *t;
  112.     char *d;
  113.  
  114.     if (!(t = strstr(str, pat)))
  115.     return;
  116.     d = strdup(t + strlen(pat));
  117.     *t = '\0';
  118.     strcat(str, rep);
  119.     strcat(str, d);
  120.     free(d);
  121. }
  122.  
  123. /******************************************************************
  124.  * Contract dirname from /usr/people/xxx to ~/ to save some length.
  125.  * Also replace the middle part of a path with X if the path is longer
  126.  * than limit. Useful when indicator is of limited length
  127.  ******************************************************************/
  128. const char *
  129. contract_dirname(const char *dir, int limit)
  130. {
  131.     static char buf[PATH_MAX];
  132.     const char *home = getenv("HOME");
  133.     char top[100];
  134.     char *t;
  135.     int l = strlen(dir);
  136.  
  137.     limit = Max(18, limit);
  138.     if (l < limit || !home)
  139.     return dir;
  140.  
  141.     strcpy(buf, dir);
  142.     pat_replace(buf, home, "~");
  143.  
  144.     /* replace middle components with ... */
  145.     if ((l = strlen(buf)) > limit)
  146.       {
  147.       int k = limit / 3 - 2;
  148.       char *p = strchr(buf + k, '/');
  149.       char *q;
  150.       int i = 0;
  151.  
  152.       q = buf + l - k;
  153.       while (*--q != '/')
  154.           ;
  155.  
  156.       if (q > p + 3)
  157.         {
  158.         /* replace whatever in between with X */
  159.         *++p = 'X';
  160.         *++p = 'X';
  161.         *++p = '\0';
  162.         strcpy(p, q);
  163.         }
  164.       }
  165.  
  166.     return buf;
  167. }
  168.  
  169. #ifdef TEST
  170.  
  171. main(int argc, char *argv[])
  172. {
  173.     char pp[2048];
  174.  
  175.     while (gets(pp))
  176.       {
  177.       fprintf(stderr, "%s=>", pp);
  178.       fprintf(stderr, "FIX: %s\n", fix_dirname(pp));
  179.       fprintf(stderr, "CON: %s\n", contract_dirname(pp, 30));
  180.       }
  181. }
  182.  
  183. #endif
  184.